/*
@hehung
email: 1398660197@qq.com
wechat: hehung95
reproduced and please indicate the source @hehung
*/

#include "app_common.h"

#define EEPROM_DEBUG
#undef EEPROM_DEBUG

#ifdef EEPROM_DEBUG
#include <stdio.h>
#define LOG(fmt, ...)        printf(fmt, ##__VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif


/* Stored address of MQ5 warning threshold */
#define EEPROM_ADDRESS_MQ5_THRESHOLD         (0x00U)
/* Data length of MQ5 warning threshold */
#define EEPROM_DATA_SIZE_MQ5_THRESHOLD       (4U)



static uint32_t timeout_ms = 500U;

static i2c_master_event_t g_i2c_callback_event;



static void Eeprom_I2C_WaitState(void);



/* Notification for EEPROM(I2C) */
void eeprom_i2c2_notification(i2c_master_callback_args_t * p_args)
{
    g_i2c_callback_event = p_args->event;
}

/* Initialize EEPROM I2C */
void Eeprom_I2c_Init(void)
{
    R_IIC_MASTER_Open(EEPROM.p_ctrl, &EEPROM_cfg);
    R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
}


/* Write one Byte to EEPROM */
void Eeprom_I2C_ByteWrite(unsigned char address, unsigned char byte)
{
    unsigned char send_buffer[2] = {};

    send_buffer[0] = address;
    send_buffer[1] = byte;
    R_IIC_MASTER_Write(&EEPROM_ctrl, &send_buffer[0], 2, false); 

    while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
    {
        R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
        timeout_ms--;
    }
    timeout_ms = 500;
}

/* Write page into EEPROM */
//page write:   page 0~31
void Eeprom_I2C_Writepage(unsigned char* ptr_write , unsigned char WriteAddr,unsigned char len) 
{

    unsigned char send_buffer[9] = {};
    send_buffer[0] = WriteAddr;

    for(unsigned char i = 0;i<len;i++)
    {
        send_buffer[1+i] = *(ptr_write+i);
    }

    R_IIC_MASTER_Write(&EEPROM_ctrl, &send_buffer[0], len+1 , false);

    while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
    {
        R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
        timeout_ms--;
    }
    timeout_ms = 500;

    Eeprom_I2C_WaitState();
}


/* Write buffer data into EEPROM */
void Eeprom_I2C_BufferWrite(uint8_t* pBuffer, uint8_t WriteAddr,uint16_t NumByteToWrite)
{
    uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

    Addr = WriteAddr % EEPROM_PAGESIZE;
    count = EEPROM_PAGESIZE - Addr;
    NumOfPage =  (uint8_t)(NumByteToWrite / EEPROM_PAGESIZE);
    NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;

    /* If WriteAddr is I2C_PageSize aligned  */
    if (Addr == 0) {
        /* If NumByteToWrite < I2C_PageSize */
        if (NumOfPage == 0) {
            Eeprom_I2C_Writepage(pBuffer, WriteAddr, NumOfSingle);
        }
        /* If NumByteToWrite > I2C_PageSize */
        else {
            while (NumOfPage--) {
                Eeprom_I2C_Writepage(pBuffer, WriteAddr, EEPROM_PAGESIZE);
                WriteAddr +=  EEPROM_PAGESIZE;
                pBuffer += EEPROM_PAGESIZE;
            }

            if (NumOfSingle!=0) {
                Eeprom_I2C_Writepage(pBuffer, WriteAddr, NumOfSingle);
            }
        }
    }
    /* If WriteAddr is not I2C_PageSize aligned  */
    else {
        /* If NumByteToWrite < I2C_PageSize */
        if (NumOfPage== 0) {
            Eeprom_I2C_Writepage(pBuffer, WriteAddr, NumOfSingle);
        }
        /* If NumByteToWrite > I2C_PageSize */
        else {
            NumByteToWrite -= count;
            NumOfPage =  (uint8_t)(NumByteToWrite / EEPROM_PAGESIZE);
            NumOfSingle = NumByteToWrite % EEPROM_PAGESIZE;

            if (count != 0) {
                Eeprom_I2C_Writepage(pBuffer, WriteAddr, count);
                WriteAddr += count;
                pBuffer += count;
            }

            while (NumOfPage--) {
                Eeprom_I2C_Writepage(pBuffer, WriteAddr, EEPROM_PAGESIZE);
                WriteAddr +=  EEPROM_PAGESIZE;
                pBuffer += EEPROM_PAGESIZE;
            }
            if (NumOfSingle != 0) {
                Eeprom_I2C_Writepage(pBuffer, WriteAddr, NumOfSingle);
            }
        }
    }
}

/* Read data from EEPROM */
void Eeprom_I2C_BufferRead(unsigned char* ptr_read,unsigned char address,unsigned char byte)
{

    unsigned char send_buffer[2] = {};

    send_buffer[0] = address;
    R_IIC_MASTER_Write(&EEPROM_ctrl, &send_buffer[0], 1, true);
    while ((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
    {
        R_BSP_SoftwareDelay(400U, BSP_DELAY_UNITS_MICROSECONDS);
        timeout_ms--;
    }
    timeout_ms = 500U;

    R_BSP_SoftwareDelay(250U, BSP_DELAY_UNITS_MICROSECONDS);

    R_IIC_MASTER_Read(&EEPROM_ctrl, ptr_read, byte, false);

}

/* EEPROM clear data */
void Eeprom_I2C_Writedrase(void)
{
    unsigned char I2c_Buf_Write[256] = {};
    for(int i = 0 ; i<256 ; i++)
    {
        I2c_Buf_Write[i] = 0xff;
    }
    Eeprom_I2C_BufferWrite(I2c_Buf_Write, 0x00 , 256);
}

/* EEPROM wait data write completed */
static void Eeprom_I2C_WaitState(void)
{
    while (timeout_ms)
    {
        R_BSP_SoftwareDelay(9U, BSP_DELAY_UNITS_MICROSECONDS);
        timeout_ms--;
    }
    timeout_ms = 500;
}

void Eeprom_ReadKeyData(void)
{
	uint8_t data_buffer[EEPROM_DATA_SIZE_MQ5_THRESHOLD] = {0, 0, 0, 0};
	uint32_t mq5_read_data;
	uint32_t eeprom_dave_data;
	
	Eeprom_I2C_BufferRead(data_buffer, EEPROM_ADDRESS_MQ5_THRESHOLD, EEPROM_DATA_SIZE_MQ5_THRESHOLD);
	DELAY_MS(10);
	eeprom_dave_data = ((uint32_t)data_buffer[0] << 24U) |
	                ((uint32_t)data_buffer[1] << 16U) |
	                ((uint32_t)data_buffer[2] << 8U)  |
	                ((uint32_t)data_buffer[3]);

	if ((0U == eeprom_dave_data) || (0xFFFFFFFFU == eeprom_dave_data))
	{
		/* Store the default data into eeprom */
		mq5_read_data = Warning_GetMq5Threshold();
		data_buffer[0] = (uint8_t)(mq5_read_data >> 24U);
		data_buffer[1] = (uint8_t)(mq5_read_data >> 16U);
		data_buffer[2] = (uint8_t)(mq5_read_data >> 8U);
		data_buffer[3] = (uint8_t)(mq5_read_data);
		
		Eeprom_I2C_BufferWrite(data_buffer, EEPROM_ADDRESS_MQ5_THRESHOLD, EEPROM_DATA_SIZE_MQ5_THRESHOLD);
		DELAY_MS(10);
		
		LOG("EEPROM: Read data from EEPROM is: %d\r\nWrite the data %d into EEPROM\r\n", eeprom_dave_data, mq5_read_data);
	}
	else
	{
		/* Update the data from EEPROM saved */
		Warning_SetMq5Threshold(eeprom_dave_data);
		
		LOG("EEPROM: Set default data %d to threshold into EEPROM\r\n", eeprom_dave_data);
	}
}

void Eeprom_UpdateKeyData(void)
{
	uint8_t data_buffer[EEPROM_DATA_SIZE_MQ5_THRESHOLD] = {0, 0, 0, 0};
	uint32_t mq5_read_data;
	uint32_t eeprom_dave_data;
	
	Eeprom_I2C_BufferRead(data_buffer, EEPROM_ADDRESS_MQ5_THRESHOLD, EEPROM_DATA_SIZE_MQ5_THRESHOLD);
	DELAY_MS(10);
	eeprom_dave_data = ((uint32_t)data_buffer[0] << 24U) |
	                ((uint32_t)data_buffer[1] << 16U) |
	                ((uint32_t)data_buffer[2] << 8U)  |
	                ((uint32_t)data_buffer[3]);
	
    mq5_read_data = Warning_GetMq5Threshold();
	
	if (eeprom_dave_data != mq5_read_data)
	{
		/* Store the default data into eeprom */
		data_buffer[0] = (uint8_t)(mq5_read_data >> 24U);
		data_buffer[1] = (uint8_t)(mq5_read_data >> 16U);
		data_buffer[2] = (uint8_t)(mq5_read_data >> 8U);
		data_buffer[3] = (uint8_t)(mq5_read_data);
		Eeprom_I2C_BufferWrite(data_buffer, EEPROM_ADDRESS_MQ5_THRESHOLD, EEPROM_DATA_SIZE_MQ5_THRESHOLD);
		DELAY_MS(10);
		
		LOG("EEPROM: Update data %d into EEPROM is successfully\r\n", mq5_read_data);
	}
	else
	{
		/* Do Nothing */
	}	
}

